#include "curve.h"
#include "qfouriertransformer.h"

Curve::Curve(QWidget *parent)
    : QWidget (parent)
{
    m_cp = new QCustomPlot(this);
    QBrush brush(QColor(100, 100, 100));
    m_cp->setBackground(brush);

    /* x轴、Y轴相关配置 */
    QPen pen;
    pen.setColor(QColor(Qt::white));
    m_cp->xAxis->setLabelColor(QColor(Qt::white)); // X轴上标识label字体颜色
    m_cp->yAxis->setLabelColor(QColor(Qt::white));
    m_cp->xAxis->setTickPen(pen);                  //  设置x轴上坐标点上对应的刻度线的颜色
    m_cp->yAxis->setTickPen(pen);
    m_cp->xAxis->setBasePen(pen);                  //  设置x轴 轴线本身的颜色
    m_cp->yAxis->setBasePen(pen);
    m_cp->xAxis->setTickLabelColor(QColor(Qt::white)); // 设置x轴刻度值文本的颜色
    m_cp->yAxis->setTickLabelColor(QColor(Qt::white));

    m_cp->xAxis->setSubTicks(true);  //  显示x轴子刻度线
    m_cp->yAxis->setSubTicks(false);  //  隐藏y轴子刻度线

    m_cp->xAxis->ticker()->setTickCount(10);
    m_cp->xAxis->ticker()->setTickStepStrategy(QCPAxisTicker::tssReadability);//可读性优于设置
    m_cp->xAxis->grid()->setVisible(true);

    //轴内区域设置
    //m_cp->axisRect()->setBackground(QBrush(Qt::black));//背景黑色
    m_cp->xAxis->grid()->setPen(QPen(QColor(220, 220, 220), 1, Qt::PenStyle::DashLine));//网格白色虚线
    m_cp->yAxis->grid()->setPen(QPen(QColor(220, 220, 220), 1, Qt::PenStyle::DashLine));//网格白色虚线
    m_cp->xAxis->grid()->setSubGridPen(QPen(QColor(200, 200, 200), 1, Qt::DotLine));//网格浅色点线
    m_cp->yAxis->grid()->setSubGridPen(QPen(QColor(200, 200, 200), 1, Qt::DotLine));//网格浅色点线
    m_cp->xAxis->grid()->setSubGridVisible(true);//显示x轴子网格线
    m_cp->yAxis->grid()->setSubGridVisible(true);//显示y轴子网格线
    m_cp->xAxis->grid()->setZeroLinePen(QPen(Qt::white));//x轴0线颜色白色
    m_cp->yAxis->grid()->setZeroLinePen(QPen(Qt::white));//y轴0线颜色白色


    QFont font;
//    font.setPointSize((float)100 / 800 * this->geometry().width());
    font = this->font();
    m_cp->xAxis->setLabelFont(font);  //  设置x轴标识label文本字体大小
    m_cp->yAxis->setLabelFont(font);  //  设置y轴标识label文本字体大小
//    font.setPointSize((float)80 / 800 * this->geometry().width());
    m_cp->xAxis->setTickLabelFont(font);
    m_cp->yAxis->setTickLabelFont(font);

    m_cp->xAxis->setRange(m_range.xMin, m_range.xMax);   //  设置x轴数据范围
    m_cp->yAxis->setRange(m_range.yMin, m_range.yMax);   //  设置y轴数据范围

    // 添加标题
    m_eTitle = new QCPTextElement(m_cp, m_title);
    m_eTitle->setTextColor(Qt::white);
    m_cp->plotLayout()->insertRow(0);
    m_cp->plotLayout()->addElement(0, 0, m_eTitle);

    //添加图例
    m_cp->legend->setVisible(true);

    // 允许用户用鼠标拖动轴范围，用鼠标滚轮缩放，点击选择图形:
//    cp->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
    m_cp->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

    /* 刷新显示 */
    m_cp->replot();

    //连接鼠标事件发出的信号，实现绑定
//    connect(cp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress(QMouseEvent*)));
//    connect(cp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*)));
//    connect(cp, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseRelease(QMouseEvent*)));

    //用installEventFilter，否则CTRL+鼠标右键选择放大区域的功能实现不了
    m_cp->installEventFilter(this);

    //初始化QRubberBand
    m_rubberBand = new QRubberBand(QRubberBand::Rectangle, m_cp);

    m_timerUpdate = new QTimer(this);
    connect(m_timerUpdate, &QTimer::timeout, this, [=](){
        m_cp->replot();

//        // test
//        static double data = 0;
//        data += 0.1;
//        if (data > 15)
//            data = 0;
//        onAddGraphData(0, data);
    });
//    m_timer->start(100);

    // init popupmenu
    m_menu = new PlotPopupMenu(this);
    m_menu->setCurve(*this);
    m_menu->setConfig(m_isScopeCurveUpdate, m_isScopeFollow, m_isPeriodUpdate, m_isPause);
    connect(m_menu, &PlotPopupMenu::selected, this, &Curve::onMenu);
    connect(m_menu, &PlotPopupMenu::fullScreen, this, &Curve::onFullScreen);
    connect(m_menu, &PlotPopupMenu::setVisi, this, &Curve::onSetVisible);

    // layout
    QVBoxLayout *vbl = new QVBoxLayout();
    vbl->addWidget(m_cp);
    setLayout(vbl);

    m_index = 0;
    m_graphVisibles.clear();

    m_periodSaveCurveData = new SaveCurveData(*this, this);
    connect(m_periodSaveCurveData, &SaveCurveData::changeStatus, this, [=](bool isStart){
        QString str;
        if (isStart)
            str =  m_title + " --- [ rec ]";
        else
            str = m_title;
        m_eTitle->setText(str);
        m_cp->replot();
    });

    if (m_isPeriodUpdate)
        m_timerUpdate->start(m_updatePeriod);
}

Curve::~Curve()
{

}

QString Curve::getGraphName(int index)
{
    if (index >= m_cp->graphCount())
        return QString();
    return m_cp->graph(index)->name();
}

QCustomPlot &Curve::getQCustomPlot()
{
    return *m_cp;
}

void Curve::setXAxisName(const QString &name)
{
    m_cp->xAxis->setLabel(name);
}

void Curve::setYAxisName(const QString &name)
{
    m_cp->yAxis->setLabel(name);
}

void Curve::setTitle(const QString &text)
{
    m_title = text;
    m_eTitle->setText(text);
    m_cp->replot();
}

QString Curve::getTitle()
{
    return m_title;
}

quint8 Curve::addGraph(const QString &name, const QColor &color)
{
    QCPGraph *graph = m_cp->addGraph();                // 增加曲线图

    m_graphCnt++;

    graph->setName(name);

    graph->setPen(QPen(QColor(color)));     // 设置曲线画笔的颜色

    graph->setLineStyle(QCPGraph::lsLine); // 设置连接线的类型 两点直线连接

    graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ScatterShape::ssCircle, 5)); //数据点o号

    // 初始都是显示
    m_graphVisibles << true;
    // 更新menu
    m_menu->setGraphCnt(m_graphCnt);
    m_menu->setVisibleMenu(m_graphVisibles);

    return (m_graphCnt - 1);
}

void Curve::setScopeFollow(bool en)
{
    m_isScopeFollow = en;
    m_menu->setConfig(m_isScopeCurveUpdate, m_isScopeFollow, m_isPeriodUpdate, m_isPause);
}

void Curve::setScopeCurveUpdate(bool en)
{
    m_isScopeCurveUpdate = en;
    m_menu->setConfig(m_isScopeCurveUpdate, m_isScopeFollow, m_isPeriodUpdate, m_isPause);
}

void Curve::setRange(double xMin, double xMax, double yMin, double yMax)
{
    m_range.xMin = xMin;
    m_range.xMax = xMax;
    m_range.yMin = yMin;
    m_range.yMax = yMax;
}

bool Curve::eventFilter(QObject *obj, QEvent *event)
{
    //按键事件
    QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
    if (keyEvent->key() == Qt::Key_Control)
    {
        if (event->type() == QEvent::KeyPress)
            m_isKeyControlPressed = true;
        else
            m_isKeyControlPressed = false;

//        event->accept();
    }
    else if (keyEvent->key() == Qt::Key_Escape)
    {
        if (m_rubberBand->isVisible())
        {
            m_rubberBand->setVisible(false);
        }
    }

    //鼠标事件
    QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
    if(mouseEvent->type() == QMouseEvent::MouseMove) //移动
    {
        if (m_rubberBand->isVisible())
        {
            m_rubberBand->setGeometry(QRect(m_rubberOrigin, mouseEvent->pos()).normalized());

            event->accept();
            return true;
        }
    }
    else if (mouseEvent->type() == QMouseEvent::MouseButtonPress) //按下
    {
        if (mouseEvent->button() == Qt::RightButton)//鼠标右键
        {
            m_menu->exec(QPoint(QCursor::pos())); //在当前位置弹出菜单
        }
        else if (mouseEvent->button() == Qt::LeftButton)
        {
            if (m_isKeyControlPressed)
            {
                m_rubberOrigin = mouseEvent->pos();
                m_rubberBand->setGeometry(QRect(m_rubberOrigin, QSize()));
                m_rubberBand->show();

                event->accept();
            }
        }
    }
    else if (mouseEvent->type() == QMouseEvent::MouseButtonRelease) //释放
    {
//        if (mouseEvent->button() == Qt::RightButton)
        {
            if (m_rubberBand->isVisible())
            {
                const QRect zoomRect = m_rubberBand->geometry();
                int xp1, yp1, xp2, yp2;
                zoomRect.getCoords(&xp1, &yp1, &xp2, &yp2);
                double x1 = m_cp->xAxis->pixelToCoord(xp1);
                double x2 = m_cp->xAxis->pixelToCoord(xp2);
                double y1 = m_cp->yAxis->pixelToCoord(yp1);
                double y2 = m_cp->yAxis->pixelToCoord(yp2);

                if (zoomRect.width() > 10 || zoomRect.height() > 10)
                {
                    m_cp->xAxis->setRange(x1, x2);
                    m_cp->yAxis->setRange(y1, y2);

                    m_cp->replot();
                }

                m_rubberBand->hide();

                event->accept();
            }
        }
    }

    return QWidget::eventFilter(obj, event);
}

void Curve::noise()
{
    if (m_index == 0)
        return;

#define NOISE_STATISTICS_COUNT	30
    //最大最小值
    double max, min;
    max = min = m_cp->graph(0)->data().data()->at(m_index - 1)->value;
    quint32 len = m_index > NOISE_STATISTICS_COUNT ? NOISE_STATISTICS_COUNT : m_index;
    for (quint32 i = 2; i <= len; i++)
    {
        double val = m_cp->graph(0)->data().data()->at(m_index - i)->value;
        if (val > max)
        {
            max = val;
        }
        if (val < min)
        {
            min = val;
        }
    }
    QMessageBox::information(this, "Noise", QString("Noise = %1, max = %2, min = %3").arg(max - min).arg(max).arg(min),
                             QMessageBox::Ok);
}

void Curve::shift()
{
    if (m_index == 0)
        return;

#define SHIFT_STATISTICS_COUNT	3000
    double origin, now;
    now = m_cp->graph(0)->data().data()->at(m_index - 1)->value;
    if (m_index > SHIFT_STATISTICS_COUNT)
        origin = m_cp->graph(0)->data().data()->at(m_index - 3000)->value;
    else
        origin = m_cp->graph(0)->data().data()->at(0)->value;

    QMessageBox::information(this, "Shift", QString("Shift = %1, now = %2, origin = %3").arg(now - origin).arg(now).arg(origin),
                             QMessageBox::Ok);
}

void Curve::save()
{
    if (m_index == 0)
        return;

    QString fileName = QFileDialog::getSaveFileName(this, "save as file", ".");
//        QString fileName = QFileDialog::getSaveFileName(this, "save as file", ".", "*.txt");
    QFile file(fileName);
    file.open(QIODevice::WriteOnly);
    if (!file.isOpen())
        return;

    QString line;
    // 第一行记录图表名称
    line.clear();
    line.append("Name : ");
    line.append(m_title);
    line.append("\n");
    file.write(line.toLatin1());

    // 第2行记录日期时间
    line.clear();
    line.append("DateTime : ");
    line.append(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
    line.append("\n");
    file.write(line.toLatin1());

    // 第3行记录x轴信息
    line.clear();
    line.append("X axis label : ");
    line.append(m_cp->xAxis->label());
    line.append("\n");
    file.write(line.toLatin1());

    // 第4行记录序号和曲线名称
    line.clear();
    line.append("index");
    for (int j = 0; j < m_cp->graphCount(); j++)
    {
        line.append(" ");
        line.append(m_cp->graph(j)->name());
    }
    line.append("\n");
    file.write(line.toLatin1());

    for (int i = 0; i < m_index; i++)
    {
        QString line;
        line.clear();
        line.append(QString::number(i));
        for (int j = 0; j < m_cp->graphCount(); j++)
        {
//            line.append(" ");
//            double x = m_cp->graph(j)->data().data()->at(i)->key;
//            line.append(" ");
//            line.append(QString::number(x));
            double y = m_cp->graph(j)->data().data()->at(i)->value;
            line.append(" ");
            line.append(QString::number(y));
        }
        line.append("\n");
        file.write(line.toLatin1());
    }
//        file.flush();

//        // must have this code.
//        ::fsync(file.handle());

    file.close();
}

void Curve::saveXY(int num)
{
    if (num >= m_graphCnt)
        return;

    QString fileName = QFileDialog::getSaveFileName(this, "save as file", ".");
//        QString fileName = QFileDialog::getSaveFileName(this, "save as file", ".", "*.txt");
    QFile file(fileName);
    file.open(QIODevice::WriteOnly);
    if (!file.isOpen())
        return;

    QString line;
    // 第一行记录图表名称
    line.clear();
    line.append("Name : ");
    line.append(m_title);
    line.append("\n");
    file.write(line.toLatin1());

    // 第2行记录日期时间
    line.clear();
    line.append("DateTime : ");
    line.append(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
    line.append("\n");
    file.write(line.toLatin1());

    // 第3行记录x轴信息
    line.clear();
    line.append("X axis label : ");
    line.append(m_cp->xAxis->label());
    line.append("\n");
    file.write(line.toLatin1());

    // 第4行记录序号和曲线名称
    line.clear();
    line.append("index");
    line.append(" ");
    line.append(m_cp->graph(num)->name());
    line.append("\n");
    file.write(line.toLatin1());

    int size = m_cp->graph(num)->data()->size();
    for (int i = 0; i < size; i++)
    {
        QString line;
        line.clear();

        // (x, y)
        double x = m_cp->graph(num)->data().data()->at(i)->key;
        line.append(" ");
        line.append(QString::number(x));
        double y = m_cp->graph(num)->data().data()->at(i)->value;
        line.append(" ");
        line.append(QString::number(y));

        line.append("\n");
        file.write(line.toLatin1());
    }
//        file.flush();

//        // must have this code.
//        ::fsync(file.handle());

    file.close();
}

void Curve::import()
{
    QString fileName = QFileDialog::getOpenFileName(this, "save as file", "/home/jiehua/pressure_data/inletpressure/ande_emptybottle");
//    QString fileName = QFileDialog::getOpenFileName(this, "save as file", ".");
//        QString fileName = QFileDialog::getSaveFileName(this, "save as file", ".", "*.txt");
    QFile file(fileName);
    file.open(QIODevice::ReadOnly);
    if (!file.isOpen())
    {
        qWarning() << "The file can not open !";
        return;
    }

    // 读取第1行的图表名称
#define NAME "Name : "
    QByteArray ba = file.readLine(100);
    if (!ba.startsWith(NAME))
    {
        file.close();
        QMessageBox::information(this, tr("Tips"), tr("The first line must starts with \"Name : \""));
        return;
    }
    ba = ba.right(ba.size() - QString(NAME).length());
    ba = ba.simplified();
    QString title = fileName + "  " + QString(ba);

    // 读取第2行的日期时间
#define DATETIME "DateTime : "
    ba = file.readLine(100);
    if (!ba.startsWith(DATETIME))
    {
        file.close();
        QMessageBox::information(this, tr("Tips"), tr("The second line must starts with \"DateTime : \""));
        return;
    }
    ba = ba.right(ba.size() - QString(DATETIME).length());
    ba = ba.simplified();
    QString datetime = QString(ba);
    qDebug() << "Date and Time is : " << datetime;

    // 读取第3行的图表名称
#define X_AXIS_LABEL "X axis label : "
    ba = file.readLine(100);
    if (!ba.startsWith(X_AXIS_LABEL))
    {
        file.close();
        QMessageBox::information(this, tr("Tips"), tr("The third line must like \"X axis label : \""));
        return;
    }
    ba = ba.right(ba.size() - QString(X_AXIS_LABEL).length());
    ba = ba.simplified();
    QString xAxisLabel = QString(ba);

    // 读取第4行的图表名称
    ba = file.readLine(100);
    QList<QByteArray> list = ba.split(' ');
    if (list.size() < 2)
    {
        file.close();
        QMessageBox::information(this, tr("Tips"), tr("The fourth line must like \"index xxx xxx xxx\""));
        return;
    }
    QList<QString> names;
    names.clear();
    for (int i = 1; i < list.size(); i++)
    {
        ba = list.at(i).trimmed();
        QString name = QString(ba);
        names << name;
    }
    QList<QColor> colors;
    colors << QColor(Qt::red) << QColor(Qt::green) << QColor(Qt::blue) << QColor(Qt::cyan);
    // 创建图表
    Curve *curve;
    curve = new Curve();
    curve ->setTitle(title);
    curve ->setXAxisName(xAxisLabel);
    for (int i = 0; i < names.size(); i++)
    {
        int j = i % colors.size();
        curve->addGraph(names.at(i), colors[j]);
    }
    curve->setAttribute(Qt::WA_DeleteOnClose, true);

#if 0
    // 读取第4行数据
    ba = file.readLine(100);
    list = ba.split(' ');
    if (list.size() < 2)
    {
        file.close();
        qWarning() << "The file has no curve data!";
        return;
    }
    int curveCnt = list.size() - 1;
    if (curveCnt >= 1)
        curve->m_cp->graph(0)->addData(index, list.at(1).toDouble());
    if (curveCnt >= 2)
        curve->m_cp->graph(1)->addData(index, list.at(2).toDouble());
    if (curveCnt >= 3)
        curve->m_cp->graph(2)->addData(index, list.at(3).toDouble());
#endif

    // 读取数据
    int index = 0;
    while (!file.atEnd())
    {
        ba = file.readLine(100);
        list = ba.split(' ');
        if (list.size() < 2)
        {
            file.close();
            QMessageBox::information(this, tr("Tips"), tr("There is no correct data in line %1").arg(index));
            return;
        }
        int curveCnt = list.size() - 1;
        for (int i = 0; i < curveCnt; i++)
        {
//            curve->m_cp->graph(i)->addData(index, list.at(i + 1).toDouble());
            curve->m_cp->graph(i)->addData(list.at(0).toDouble(), list.at(i + 1).toDouble()); // 实际(x, y)
        }
        index++;
    }

    file.close();

    curve->resize(this->size());
    curve->show();
    curve->m_cp->rescaleAxes();
    curve->m_cp->replot();
}

void Curve::savePeriod()
{
    m_saveCurveDialog = new SaveCurveDialog(this);
    m_saveCurveDialog->setConfig(m_periodSaveCurveData->getPeriod(), m_periodSaveCurveData->getFileName());
    m_saveCurveDialog->setStatus(m_periodSaveCurveData->getStatus());
    connect(m_saveCurveDialog, &SaveCurveDialog::changeConfig, this, [=](int period, const QString &fileName){
        m_periodSaveCurveData->setPeriod(period);
        m_periodSaveCurveData->setFileName(fileName);
    });
    connect(m_saveCurveDialog, &SaveCurveDialog::changeStatus, this, [=](bool isStart){
        isStart ? m_periodSaveCurveData->start() : m_periodSaveCurveData->stop();
        m_isPeriodSave = isStart;
    });
    m_saveCurveDialog->open();
}

void Curve::fft()
{
    QFourierTransformer transformer;

    int size = m_cp->graph(0)->data()->size();
    qDebug() << size;
    float result = log(float(size)) / log(2.0);
    size = pow(2, (int)result);
    qDebug() << result << size;

    QVector<float> samples(size);
    QVector<float> fft(size);
    for (int i = 0; i < size; i++)
    {
        // (x, y)
        double x = m_cp->graph(0)->data().data()->at(i)->key;
        double y = m_cp->graph(0)->data().data()->at(i)->value;
        samples[i] = y;
    }

    if(transformer.setSize(size) == QFourierTransformer::VariableSize)
    {
        qDebug("This size is not a default fixed size of QRealFourier. Using a variable size instead.\n");
    }
    else if(transformer.setSize(size) == QFourierTransformer::InvalidSize)
    {
        qDebug("Invalid FFT size %d.\n", size);
        return;
    }

    transformer.forwardTransform(samples.data(), fft.data());

    //
    Curve *fftCurve = new Curve();
    fftCurve->setTitle("FFT Curve");
    fftCurve->setXAxisName(tr("cnt"));
    fftCurve->addGraph(tr("raw data"), QColor(Qt::red));
    fftCurve->addGraph(tr("fft data"), QColor(Qt::green));
    fftCurve->setGeometry(1000, 200, 800, 600);
    fftCurve->show();
    for (int i = 0; i < size; i++)
    {
        fftCurve->onAddGraphData(2, samples.at(i), fft.at(i));
    }
}

void Curve::closeEvent(QCloseEvent *event)
{

}

void Curve::onMenu(PlotPopupMenu::MenuType type, bool checked)
{
    switch (type)
    {
    case PlotPopupMenu::MT_Clear:
        {
            int ret = QMessageBox::warning(this, tr("Warning"), tr("Is clear all graphs?"),
                                           QMessageBox::StandardButton::Yes,
                                           QMessageBox::StandardButton::Cancel);
            if (ret == QMessageBox::StandardButton::Yes)
            {
                m_index = 0;
                for (int i = 0; i < m_cp->graphCount(); i++)
                {
                    m_cp->graph(i)->data().data()->clear();
                }
                m_cp->replot();
            }
        }
        break;
    case PlotPopupMenu::MT_Range:
        m_rangeDialog = new RangeDialog(m_range, this);
        connect(m_rangeDialog, &RangeDialog::setRange, this, &Curve::onChangeRange);
        m_rangeDialog->open();
        break;
    case PlotPopupMenu::MT_UpdateTime:
        m_updateTimeDialog = new UpdateTimeDialog(m_updatePeriod, this);
        connect(m_updateTimeDialog, &UpdateTimeDialog::setUpdatePeriod, this, &Curve::onChangeUpdatePeriod);
        m_updateTimeDialog->open();
        break;
    case PlotPopupMenu::MT_ScopeFollow:
        m_isScopeFollow = checked;
        break;
    case PlotPopupMenu::MT_ScopeCurveUpdate:
        m_isScopeCurveUpdate = checked;
        break;
    case PlotPopupMenu::MT_PeriodUpdate:
        m_isPeriodUpdate = checked;
        if (!m_isPeriodUpdate)
            m_timerUpdate->stop();
        else
            m_timerUpdate->start(m_updatePeriod);
        break;
    case PlotPopupMenu::MT_Pause:
        m_isPause = checked;
        break;
    case PlotPopupMenu::MT_Noise:
        noise();
        break;
    case PlotPopupMenu::MT_Shift:
        shift();
        break;
    case PlotPopupMenu::MT_Save:
        save();
        break;
    case PlotPopupMenu::MT_SaveAsPng:
        {
            QString fileName = QFileDialog::getSaveFileName(this, "save as png", ".");
            if (!fileName.isEmpty())
                m_cp->savePng(fileName);
        }
        break;
    case PlotPopupMenu::MT_Import:
        import();
        break;
    case PlotPopupMenu::MT_SavePeriod:
        savePeriod();
        break;
    case PlotPopupMenu::MT_FFT:
        fft();
        break;
    default:
        qWarning() << "the PlotPopupMenu must Error!";
        break;
    }
}

void Curve::onClear(int graphIndex)
{
    if (graphIndex > m_cp->graphCount())
        return;

    if (graphIndex == m_cp->graphCount())
    {
        m_index = 0;
        for (int i = 0; i < m_cp->graphCount(); i++)
        {
            m_cp->graph(i)->data().data()->clear();
        }
    }
    else
    {
        m_cp->graph(graphIndex)->data().data()->clear();
    }
    m_cp->replot();
}

void Curve::onFullScreen(int graphIndex)
{
    if (graphIndex > m_cp->graphCount())
        return;

    // 所有曲线全屏
    if (graphIndex == m_cp->graphCount())
    {
        m_cp->rescaleAxes(true);
    }
    else
    {
        m_cp->graph(graphIndex)->rescaleAxes();
    }

    m_cp->replot();
    m_scope = m_cp->xAxis->range().size();

    m_range.xMin = m_cp->xAxis->range().lower;
    m_range.xMax = m_cp->xAxis->range().upper;
    m_range.yMin = m_cp->yAxis->range().lower;
    m_range.yMax = m_cp->yAxis->range().upper;
}

void Curve::onSetVisible(int graphIndex, bool checked)
{
    if (graphIndex > m_cp->graphCount())
        return;

    m_cp->graph(graphIndex)->setVisible(checked);
    m_graphVisibles[graphIndex] = checked;
}

void Curve::onChangeRange(RangeDialog::Range range)
{
    this->m_range = range;

    m_cp->xAxis->setRange(range.xMin, range.xMax);
    m_cp->yAxis->setRange(range.yMin, range.yMax);
    m_cp->replot();
}

void Curve::onChangeUpdatePeriod(double time)
{
    this->m_updatePeriod = time;

    m_timerUpdate->setInterval(time);
}

void Curve::onAddGraphData(int num, ...)
{
    if (num > m_cp->graphCount())
        return;

    if(m_isPause)
        return;

    if (m_isScopeCurveUpdate)
    {
        double xMax = m_cp->xAxis->range().upper;
        if (m_index > xMax)
        {
            m_index = 0;
            for (int i = 0; i < m_cp->graphCount(); i++)
            {
                m_cp->graph(i)->data().data()->clear();
            }
            m_cp->xAxis->setRange(0, xMax);
        }
    }

    // 找出数据
    va_list ap;
    va_start(ap, num);
    for (int i = 0; i < num; i++)
    {
        double d = va_arg(ap, double);
        m_cp->graph(i)->addData(m_index, d);
    }
    va_end(ap);

    if (m_isPeriodSave)
    {
        QString line;
        line.clear();
        line.append(QString::number(m_index));
        for (int j = 0; j < m_cp->graphCount(); j++)
        {
            double data = m_cp->graph(j)->data().data()->at(m_index)->value;
            line.append(" ");
            line.append(QString::number(data));
        }
        line.append("\n");
        m_periodSaveCurveData->addData(line);
    }

    if (!m_isPeriodUpdate)
        m_cp->replot();

    if (!m_isScopeCurveUpdate && m_isScopeFollow)
    {
        m_range.xMax = m_cp->xAxis->range().upper;
        if (m_index > m_range.xMax)
        {
            m_scope = m_cp->xAxis->range().size();
            m_cp->xAxis->setRange(m_index - m_scope, m_index);
        }
    }
    else
    {
        //cp->graph(0)->rescaleAxes(); //自动调整坐标轴
    }
    m_index++;
}

void Curve::onAddGraphPoint(int num, double x, double y)
{
    if (num >= m_graphCnt)
        return;
    m_cp->graph(num)->addData(x, y);
}
